using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using System.Text;
using System.Threading.Tasks;


#if UNITY_ANDROID
using UnityEngine.Android;
#endif

namespace Galplay {
  public class GameResources : MonoBehaviour {
    private static GameResources _instance;
    public static GameResources Instance {
      get {
        if (_instance == null) {
#if UNITY_ANDROID
          if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead)) {
            Permission.RequestUserPermission(Permission.ExternalStorageRead);
          }
#endif

          GameObject obj = new GameObject("GameResources");
          _instance = obj.AddComponent<GameResources>();
          DontDestroyOnLoad(obj);
        }
        return _instance;
      }
    }

    // 纹理缓存字典 [路径, 纹理数据]
    private Dictionary<string, TextureData> _textureCache = new Dictionary<string, TextureData>();

    // 音频缓存字典 [路径, 音频数据]
    private Dictionary<string, AudioData> _audioCache = new Dictionary<string, AudioData>();

    // 纹理数据包装类
    private class TextureData {
      public Texture2D texture;
      public Sprite sprite;
      public int referenceCount;

      public TextureData(Texture2D tex, Sprite spr) {
        texture = tex;
        sprite = spr;
        referenceCount = 1;
      }
    }

    // 音频数据包装类
    private class AudioData {
      public AudioClip clip;
      public int referenceCount;

      public AudioData(AudioClip audioClip) {
        clip = audioClip;
        referenceCount = 1;
      }
    }

    #region 图片加载功能（保持不变）
    /// <summary>
    // 异步加载图片
    /// </summary>
    public void LoadImageAsync(string path, Action<Sprite> callback) {
      if (_textureCache.TryGetValue(path, out TextureData cachedData)) {
        cachedData.referenceCount++;
        callback(cachedData.sprite);
        return;
      }

      StartCoroutine(ReadFileBytesCoroutine(path, (fileData) => {
        callback(CreateSprite(path, fileData));
      }));
    }

    public void LoadImageAsync(PackAssetItem zipAsset, Action<Sprite> callback) {
      if (zipAsset == null) { callback.Invoke(null); return; }

      if (_textureCache.TryGetValue(zipAsset.Path, out TextureData cachedData)) {
        cachedData.referenceCount++;
        callback(cachedData.sprite);
        return;
      }

      StartCoroutine(ReadFileBytesCoroutine(zipAsset, (fileData) => {
        callback(CreateSprite(zipAsset.Path, fileData));
      }));
    }

    /// <summary>
    /// 异步加载文本文件内容
    /// </summary>
    public void LoadTextAsync(string path, Action<string> callback) {
      StartCoroutine(ReadFileBytesCoroutine(path, (bytes) => {
        callback.Invoke(bytes == null ? null : Encoding.UTF8.GetString(bytes));
      }));
    }

    /// <summary>
    /// 异步加载音频文件
    /// </summary>
    public void LoadAudioAsync(string path, Action<AudioClip> callback) {
      StartCoroutine(ReadFileBytesCoroutine(path, (fileData) => {
        callback?.Invoke(LoadAudio(fileData, path));
      }));
    }

    public void LoadAudioAsync(PackAssetItem zipAsset, Action<AudioClip> callback) {
      StartCoroutine(ReadFileBytesCoroutine(zipAsset, (fileData) => {
        callback?.Invoke(LoadAudio(fileData, zipAsset.Path));
      }));
    }


    private Sprite CreateSprite(string path, byte[] fileData) {
      if (fileData == null || fileData.Length == 0) {
        Debuger.LogError("File data is empty");
        return null;
      }

      if (_textureCache.TryGetValue(path, out TextureData cachedData)) {
        cachedData.referenceCount++;
        return cachedData.sprite;
      }

      string extension = Path.GetExtension(path).ToLower();
      if (extension != ".png" && extension != ".jpg" && extension != ".jpeg") {
        Debuger.LogError("Only .png and .jpg/.jpeg files are supported");
        return null;
      }

      Texture2D texture = new Texture2D(2, 2);
      if (!texture.LoadImage(fileData)) {
        Debuger.LogError("Failed to load image data");
        Destroy(texture);
        return null;
      }

      Sprite sprite = Sprite.Create(
          texture,
          new Rect(0, 0, texture.width, texture.height),
          new Vector2(0.5f, 0.5f)
      );

      _textureCache[path] = new TextureData(texture, sprite);
      return sprite;
    }
    #endregion

    #region 新增音频加载功能



    private AudioClip LoadAudio(byte[] bytes, string path) {
      // 检查缓存
      if (_audioCache.TryGetValue(path, out AudioData cachedData)) {
        cachedData.referenceCount++;
        return cachedData.clip;
      }

      // 根据文件扩展名确定AudioType
      AudioType audioType = GetAudioTypeFromExtension(path);
      if (audioType == AudioType.UNKNOWN) {
        Debuger.LogError($"Unsupported audio format: {path}");
        return null;
      }

      AudioClip clip = null;
      if (audioType == AudioType.OGGVORBIS) {
        clip = AudioUtils.CreateFromOgg(bytes);
      } else if (audioType == AudioType.WAV) {
        clip = AudioUtils.CreateFromWav(bytes);
      } else {
        return null;
      }

      _audioCache[path] = new AudioData(clip);
      return clip;
    }

    /// <summary>
    /// 根据文件扩展名获取对应的AudioType
    /// </summary>
    private AudioType GetAudioTypeFromExtension(string path) {
      string extension = Path.GetExtension(path).ToLower();

      switch (extension) {
        case ".wav": return AudioType.WAV;
        case ".ogg": return AudioType.OGGVORBIS;
        case ".mp3":
          // Unity没有原生MP3支持，需要使用第三方库或转换为其他格式
          Debuger.LogWarning("MP3 is not natively supported, consider using WAV or OGG");
          return AudioType.UNKNOWN;
        case ".aiff":
        case ".aif": return AudioType.AIFF;
        default: return AudioType.UNKNOWN;
      }
    }

    #endregion

    #region 共享工具方法
    private IEnumerator ReadFileBytesCoroutine(string path, Action<byte[]> callback) {
      if (string.IsNullOrEmpty(path)) {
        Debuger.LogError("Path cannot be null or empty");
        callback?.Invoke(null);
        yield break;
      }

      if (!File.Exists(path)) {
        Debuger.LogError($"File not found: {path}");
        callback?.Invoke(null);
        yield break;
      }

      byte[] fileData = null;

      try {
        fileData = File.ReadAllBytes(path);
      } catch (Exception ex) {
        Debuger.LogError($"Read file error: {ex.Message}");
        callback?.Invoke(null);
        yield break;
      }

      if (fileData == null || fileData.Length == 0) {
        Debuger.LogError("File data is empty");
        callback?.Invoke(null);
        yield break;
      }

      callback?.Invoke(fileData);
    }

    private IEnumerator ReadFileBytesCoroutine(PackAssetItem file, Action<byte[]> callback) {
      if (file == null) {
        callback?.Invoke(null);
        yield break;
      }

      byte[] fileData = null;

      try {
        fileData = file.GetBytes();
      } catch (Exception ex) {
        Debuger.LogError($"ZipAssetFile({file.Owner.AssetsPath} => {file.Path}) Read file error: {ex.Message}");
        callback?.Invoke(null);
        yield break;
      }

      callback?.Invoke(fileData);
    }


    #endregion

    #region 资源管理
    public void UnloadImage(string path) {
      if (_textureCache.TryGetValue(path, out TextureData data)) {
        data.referenceCount--;

        if (data.referenceCount <= 0) {
          if (data.texture != null)
            Destroy(data.texture);

          if (data.sprite != null)
            Destroy(data.sprite);

          _textureCache.Remove(path);
        }
      }
    }

    public void UnloadAudio(string path) {
      if (_audioCache.TryGetValue(path, out AudioData data)) {
        data.referenceCount--;

        if (data.referenceCount <= 0) {
          if (data.clip != null)
            Destroy(data.clip);

          _audioCache.Remove(path);
        }
      }
    }

    public void ClearAll() {
      // 清理图片资源
      foreach (var kvp in _textureCache) {
        if (kvp.Value.texture != null)
          Destroy(kvp.Value.texture);

        if (kvp.Value.sprite != null)
          Destroy(kvp.Value.sprite);
      }
      _textureCache.Clear();

      // 清理音频资源
      foreach (var kvp in _audioCache) {
        if (kvp.Value.clip != null)
          Destroy(kvp.Value.clip);
      }
      _audioCache.Clear();
    }
    #endregion

    private void OnDestroy() {
      ClearAll();
    }
  }
}